#include "client.h"
#include <QDebug>

client::client(QTextEdit *newEd) {
    editor = newEd;
    QObject::connect(editor->document(), SIGNAL(contentsChange(int, int, int)), this, SLOT(textChanged(int, int, int)));

    sock = NULL;
    rev = 0;
    id = -1;
}

client::~client() {
    if (sock != NULL)
        delete sock;
}

bool client::connect(QString address, int port)
{
    sock = new QTcpSocket(this);
    sock->connectToHost(address, port);

    QObject::connect(sock, SIGNAL(readyRead()), this, SLOT(receiveChange()));

    return sock->isValid();
}

void client::textChanged(const int pos, const int numRemoved, const int numAdded) {

    message addMsg, remMsg;

    if (numAdded > 0) {
        addMsg.setType(ADD);
        addMsg.setLen(numAdded);
        addMsg.setId(id);
        addMsg.setPos(pos);
        addMsg.setRev(rev);
        addMsg.setData((editor->toPlainText()).mid(pos,numAdded));
    }

    if (numRemoved > 0) {
        remMsg.setType(REMOVE);
        remMsg.setLen(numRemoved);
        remMsg.setRev(rev);
        remMsg.setPos(pos);
        remMsg.setId(id);

        sock->write(remMsg.toBytes());
    }

    if (numAdded > 0)
        sock->write(addMsg.toBytes());
}

void client::receiveChange() {
    QByteArray rawMsg = sock->readAll();

    //split up in case we get multiple messages
    do {
        message msg(rawMsg);
        updateText(msg);

        qDebug() << "CLIENT RECIEVES " << msg.toBytes();

        rawMsg.remove(0, msg.toBytes().length());
    } while (rawMsg.length() != 0);
}

void client::updateText(message msg) {

    editor->document()->blockSignals(true);
    QTextCursor cur = editor->textCursor(); //save cursor position
    int curPos = cur.position();
    int curMod = 0; //how much to move cursor by

    if (msg.getType() == ADD) {
        doc.insert(msg.getPos(),msg.getData());
        curMod = msg.getLen();
    }
    else if (msg.getType() == REMOVE) {
        doc.remove(msg.getPos(), msg.getLen());
        curMod = -msg.getLen();
    }
    else if (msg.getType() == SEND_DOC) {
        if (id == -1)
            id = msg.getId();

        doc = msg.getData();
        curPos = 0; //move cursor to beginning
    }
    else if (msg.getType() == HASH) {
        QByteArray myHash = QCryptographicHash::hash(doc.toAscii(), QCryptographicHash::Md5);

        if (myHash != msg.getData())
            sock->write(message(REQUEST_DOC).toBytes());
    }

    //update the actual document
    editor->setPlainText(doc);

    if (msg.getPos() < curPos && msg.getId() != id)
        curPos += curMod;

    if (curPos > doc.length())
        curPos = doc.length();

    cur.setPosition(curPos);
    editor->setTextCursor(cur);

    editor->document()->blockSignals(false);

    rev = msg.getRev() + 1; //update the revision number
}


